package ca.scotthyndman.as2haxe.dom;

import java.util.ArrayList;
import java.util.List;

import ca.scotthyndman.as2haxe.dom.visitor.IVisitable;
import ca.scotthyndman.as2haxe.dom.visitor.IVisitor;

/**
 * Represents a field in an object.
 */
public class ASObjectLiteralField extends ASTNode implements IVisitable {

	/**
	 * The "name" structural property of this node type.
	 * 
	 * @since 3.0
	 */
	public static final ASChildPropertyDescriptor NAME_PROPERTY = new ASChildPropertyDescriptor(
			ASObjectLiteralField.class, "name", ASSimpleName.class, true);

	/**
	 * The "value" structural property of this node type.
	 * 
	 * @since 3.0
	 */
	public static final ASChildPropertyDescriptor VALUE_PROPERTY = new ASChildPropertyDescriptor(
			ASObjectLiteralField.class, "value", ASExpression.class, true);

	/**
	 * A list of property descriptors (element type:
	 * {@link ASPropertyDescriptor}), or null if uninitialized.
	 */
	private static final List<ASPropertyDescriptor> PROPERTY_DESCRIPTORS;

	static {
		List<Object> properyList = new ArrayList<Object>(3);
		createPropertyList(ASObjectLiteralField.class, properyList);
		addProperty(NAME_PROPERTY, properyList);
		addProperty(VALUE_PROPERTY, properyList);
		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
	}

	/**
	 * Returns a list of structural property descriptors for this node type.
	 * Clients must not modify the result.
	 * 
	 * @return a list of property descriptors
	 */
	public static List propertyDescriptors() {
		return PROPERTY_DESCRIPTORS;
	}

	//
	// ======== MEMBERS
	//

	private ASSimpleName name;

	private ASExpression value;

	/**
	 * Constructs a new instance of ASObjectLiteralField
	 * 
	 * @param ast
	 *            The abstract syntax tree that owns this element
	 */
	public ASObjectLiteralField(AST ast) {
		super(ast);
	}

	/**
	 * @param name
	 *            the name to set
	 */
	public void setName(ASSimpleName name) {
		if (name == null) {
			throw new IllegalArgumentException();
		}
		ASTNode oldChild = this.name;
		preReplaceChild(oldChild, name, NAME_PROPERTY);
		this.name = name;
		postReplaceChild(oldChild, name, NAME_PROPERTY);
	}

	/**
	 * @return the name
	 */
	public ASSimpleName getName() {
		return name;
	}

	/**
	 * @param value
	 *            the value to set
	 */
	public void setValue(ASExpression value) {
		if (value == null) {
			throw new IllegalArgumentException();
		}
		ASTNode oldChild = this.value;
		preReplaceChild(oldChild, value, VALUE_PROPERTY);
		this.value = value;
		postReplaceChild(oldChild, value, VALUE_PROPERTY);
	}

	/**
	 * @return the value
	 */
	public ASExpression getValue() {
		return value;
	}
	
	//
	// ======== INTERNAL GET SET
	//

	/*
	 * (omit javadoc for this method) Method declared on ASTNode.
	 */
	final ASTNode internalGetSetChildProperty(
			ASChildPropertyDescriptor property, boolean get, ASTNode child) {
		if (property == NAME_PROPERTY) {
			if (get) {
				return getName();
			} else {
				setName((ASSimpleName) child);
				return null;
			}
		}
		if (property == VALUE_PROPERTY) {
			if (get) {
				return getValue();
			} else {
				setValue((ASExpression) child);
				return null;
			}
		}
		
		// allow default implementation to flag the error
		return super.internalGetSetChildProperty(property, get, child);
	}


	// ====== VISITOR AND TO STRING

	@Override
	public String toString() {
		return getName().toString() + ": " + getValue().toString();
	}

	public void accept(IVisitor as2Visitor, boolean recursive) {
		recursive = as2Visitor.visit(this);

		if (recursive) {
			getName().accept(as2Visitor, recursive);
			getValue().accept(as2Visitor, recursive);
		}
	}

}
